package com.netx.generics.util;
import com.netx.generics.translation.FirstStep;
import com.netx.generics.translation.GenericScanner;
import com.netx.generics.translation.RecognizeException;
import com.netx.generics.translation.Recognizer;
import com.netx.generics.translation.Recognizers;
import com.netx.generics.translation.Results;
import com.netx.generics.translation.Token;
import java.io.StringReader;


class BuiltinScanner extends FirstStep<String> {

	public BuiltinScanner(String expression) {
		super(expression);
	}
	
	public Object performWork(Results r) {
		String expression = getInitialObject();
		return new InternalScanner(expression).performWork(r);
	}
	
	private class InternalScanner extends GenericScanner {
		public InternalScanner(String expression) {
			super(new StringReader(expression),
				new Recognizer[] {
					new Recognizers.StringRecognizer("'\""),
					new Recognizers.NumberRecognizer(true),
					new Recognizers.OperatorRecognizer("+"),
					new Recognizers.SeparatorRecognizer("(,)"),
					new TextRecognizer(),
					new FunctionRecognizer()
				},
				true,
				null
			);
		}
	}
	
	private class TextRecognizer implements Recognizer {
		public Token recognize(Results r, String line, int lineNum, int currentPos) throws RecognizeException {
			if(currentPos >= line.length() || line.charAt(currentPos) == '$') {
				return null;
			}
			int initialPos = currentPos;
			while(currentPos < line.length() && line.charAt(currentPos) != '$') {
				if(line.charAt(currentPos) == '\\') {
					currentPos++;
					// Check escape character:
					if(currentPos == line.length()) {
						throw new RecognizeException("expected escape character", currentPos, currentPos);
					}
					else if("$()\"\'".indexOf(line.charAt(currentPos)) == -1) {
						throw new RecognizeException("illegal TEXT escape characer: '"+line.charAt(currentPos)+"'", currentPos, currentPos+1);
					}
				}
				currentPos++;
			}
			return new BuiltinToken(BuiltinToken.TEXT, lineNum, initialPos, currentPos, line);
		}
	}
	
	private class FunctionRecognizer extends Recognizers.IdentifierRecognizer {
		public FunctionRecognizer() {
			super(true, "$", "_");
		}

		public Token recognize(Results r, String line, int lineNum, int currentPos) throws RecognizeException {
			if(line.charAt(currentPos) != '$') {
				return null;
			}
			Token t = super.recognize(r, line, lineNum, currentPos);
			return new BuiltinToken(BuiltinToken.FUNCTION, lineNum, t.getIndex(), t.getIndex()+t.getLength(), line);
		}
	}
}